#!/opt/python/bin/python

import optparse
import os
import tempfile

class BadCommandLineError(Exception):
    def __init__(self, msg, retcode):
        self.msg = msg
        self.retcode = retcode

    def __str__(self):
        return self.msg


def chunk_filenames(files):
    maxlen = 950

    tmp_files = files[:]

    chunks = []
    while len(tmp_files):
        chunk = ''
        while len(tmp_files) and len(chunk) + len(tmp_files[0]) < maxlen:
            chunk += tmp_files.pop()
            chunk += ' '
        
        chunks.append(chunk)

    return chunks

def main():
    """
    Usage: %prog [opts] hbook_files.txt | file1.hbook file2.hbook [file3.hbook [...]]
    
    Write out a kumac for merging the files supplied on the command line or 
    listed in `hbook_files.txt'.
    """

    op = optparse.OptionParser(usage=main.__doc__)
    
    op.add_option("-k", "--kumac-output", dest='kumac_out', default=None, 
                  help='Write merge kumac to PATH', metavar='PATH')
    op.add_option("-o", "--hbook-output", dest='hbook_out', default=None, 
                  help='Within merge kumac, write HBOOK output to PATH', metavar='PATH')
    
    opts, args = op.parse_args()

    if len(args) == 0:
        msg = "Please supply two or more HBOOK files "
        msg += "or a text file with a list of HBOOK files."
        raise BadCommandLineError(msg, -1)

    if len(args) == 1:
        ext = args[0].rsplit('.', 1)[1]
        if ext == 'hbook':
            msg = "Only one argument supplied and it has extension `hbook'--"
            msg += "please supply two or more HBOOK files "
            msg += "or a text file with a list of HBOOK files."
            
            raise BadCommandLineError(msg, -2)

        else:
            with open(args[0]) as fp:
                hbook_files = [l.strip() for l in fp]
            
            if opts.kumac_out is None:
                opts.kumac_out = args[0].rsplit('.', 1)[0] + '.merge.kumac'

            if opts.hbook_out is None:
                opts.hbook_out = opts.kumac_out.rsplit('.', 1)[0] + '.hbook'

    else:
        hbook_files = args[:]


    hbook_files.sort()
    hbook_files.reverse()

    if opts.kumac_out is None:
        opts.kumac_out = "merge.kumac"

    if opts.hbook_out is None:
        opts.hbook_out = opts.kumac_out.rsplit('.', 1)[0] + '.hbook'

    with open(opts.kumac_out, 'w') as fp:    
        chunks = chunk_filenames(hbook_files)
        while len(chunks) != 1:
            intermediate_files = [
                tempfile.mkstemp(suffix='.hbook',
                                 prefix=os.path.join(os.getcwd(), 'tmp'))[1]
                for i in xrange(len(chunks))]

            for im_path, chunk in zip(intermediate_files, chunks):
                if len(chunk) < 2:
                    intermediate_files.append(chunk)
                    break
            
                fp.write("/ntuple/hmerge LRECL 32768\n")
            
                fp.write("/ntuple/hmerge {0} {1}\n".format(im_path, chunk))
                fp.write("\n")
            
            intermediate_files.sort()
            intermediate_files.reverse()
            chunks = chunk_filenames(intermediate_files)
        
        fp.write("/ntuple/hmerge LRECL 32768\n")
        fp.write("/ntuple/hmerge {0} {1}\n".format(opts.hbook_out, ' '.join(chunks)))
        fp.write("\n")        
        

    print "Output left in", opts.kumac_out, ", HBOOK will be left in", opts.hbook_out

    return 0


if __name__ == '__main__':
    try:
        import sys
        sys.exit(main())
    except BadCommandLineError, e:
        import os
        sys.stderr.write(str(e) + "\n")
        sys.stderr.write("See `{0} -h' for more.\n".format(os.path.basename(sys.argv[0])))
        sys.stderr.flush()
        sys.exit(e.retcode)
            
